// #include "util.hpp"
// #include "level.hpp"
// #include "message.hpp"
// #include "format.hpp"
// #include "sink.hpp"
// #include "logger.hpp"
// #include "buffer.hpp"
// #include "looper.hpp"
// #include <unistd.h>

#include "../logs/log.h"

using namespace std;

enum class TimeGap
{
    SECOND,
    MINUTE,
    HUOR,
    DAY
};

// 拓展落地方式：滚动时间间隔
class rolltime_sink : public log::log_sink
{
public:
    rolltime_sink(const std::string &base_name, TimeGap gap)
    :_base_name(base_name)
    {
        switch(gap)
        {
            case TimeGap::SECOND : _gap_size = 1; break;
            case TimeGap::MINUTE : _gap_size = 60; break;
            case TimeGap::HUOR : _gap_size = 3600; break;
            case TimeGap::DAY : _gap_size = 3600 * 24; break;
            default : break;
        }

        // 创建目录
        log::tools::file::creat_directory(log::tools::file::get_path(base_name));

        if(_gap_size == 1)
            _creat_gap = log::tools::get_time::_get_time();
        else
            _creat_gap = log::tools::get_time::_get_time() % _gap_size;
    }

    void log(const char *data, size_t len)
    {
        // 初始化
        file_init();
        _ofs.write(data, len);
        if(_ofs.good() == false)
        {
            std::cout << "滚动时间间隔，日志写入失败" << endl;
            exit(-1);
        }
    }

private:
    void file_init()
    {
        size_t now_gap = log::tools::get_time::_get_time() % _gap_size;
        if(_gap_size == 1)
            now_gap = log::tools::get_time::_get_time();

        if(_ofs.is_open() == false || _creat_gap != now_gap)
        {
            _ofs.close();
            std::string file_name = creat_file_name();
            _ofs.open(file_name, std::ios::binary | std::ios::app);
            if(_ofs.is_open() == false)
            {
                std::cout << "滚动时间间隔，文件打开失败" << endl;
                exit(-1);
            }
        }
    }

    std::string creat_file_name()
    {
        std::stringstream file_name;
        time_t time = log::tools::get_time::_get_time();
        struct tm res;
        localtime_r(&time, &res);
        file_name << _base_name;
        //file_name << res.tm_year + 1900 << '-' << res.tm_mon + 1 << '-'  << res.tm_mday;
        //file_name << " ";
        file_name << res.tm_hour << '-' << res.tm_min + 1 << '-'  << res.tm_sec;
        file_name << ".log";
        return file_name.str();
    }

private:
    std::string _base_name;
    std::ofstream _ofs;
    size_t _creat_gap;
    size_t _gap_size;
};

void test_util()
{
    cout << log::tools::get_time::_get_time() << endl;
    string path("./xyz/abc/sss");
    log::tools::file::creat_directory(path);
    //dir(path.c_str(), 0777);
}

void test_level()
{
    log::log_level::level l;
    cout << log::log_level::to_string(l) << endl;
    l = log::log_level::FATAL;
    cout << log::log_level::to_string(l) << endl;
}

void test_format()
{
    log::log_message lm(log::log_level::FATAL, "violet", 100, "main", "日志消息测试");
    log::formatter f;
    //log::formatter f("xyz%%%l%m");
    //log::formatter f("xyz%d{sss{");
    //log::formatter f("xyz%%%l%x%y%z");
    //log::formatter f("xyz%f%");
    string s = f.format(lm);
    cout << s << endl;
}

void test_sink()
{
    log::log_message lm(log::log_level::FATAL, "violet", 100, "main", "日志消息测试");
    log::formatter fmt;
    std::string str = fmt.format(lm);
    // log::log_sink::ptr stdout_ls = log::sink_factory::creat<log::stdout_sink>();
    // log::log_sink::ptr file_ls = log::sink_factory::creat<log::file_sink>("./logfile/file_sink.log");
    // log::log_sink::ptr roll_ls = log::sink_factory::creat<log::rollsize_sink>("./logfile/roll-", 4096);
    // stdout_ls->log(str.c_str(), str.size());
    // file_ls->log(str.c_str(), str.size());
    // size_t size = 0;
    // size_t cnt = 1;
    // while(size < 4096 * 10)
    // {
    //     string temp = std::to_string(cnt++) + str;
    //     roll_ls->log(temp.c_str(), temp.size());
    //     size += temp.size();
    // }
    log::log_sink::ptr rolltime_ls = log::sink_factory::creat<rolltime_sink>("./logfile/rolltime-", TimeGap::SECOND);
    size_t time_cnt = 3;
    size_t start = (size_t)log::tools::get_time::_get_time();
    size_t cnt = 1;
    while((size_t)log::tools::get_time::_get_time() < start + 3)
    {
        string temp = std::to_string(cnt++) + str;
        rolltime_ls->log(temp.c_str(), temp.size());
        usleep(1000);
    }
}

void test_logger()
{
    // std::string logger_name = "sync_logger";
    // log::log_level::level level = log::log_level::level::DEBUG;
    // log::formatter::ptr formatter(new log::formatter());

    // log::log_sink::ptr stdout_ls = log::sink_factory::creat<log::stdout_sink>();
    // log::log_sink::ptr file_ls = log::sink_factory::creat<log::file_sink>("./logfile/file_sink.log");
    // log::log_sink::ptr rollsize_ls = log::sink_factory::creat<log::rollsize_sink>("./logfile/roll-", 4096);
    // std::vector<log::log_sink::ptr> sinks = {stdout_ls, file_ls, rollsize_ls};

    // log::logger::ptr logger(new log::sync_logger(logger_name, level, formatter, sinks));

    //log::build_logger* b = new log::local_build_logger();
    std::unique_ptr<log::build_logger> b(new log::local_build_logger());
    b->build_logger_name("sync_logger");
    b->build_formatter("%d %l %f %m%N");
    b->build_logger_type(log::logger_type::LOGGER_SYNC);
    b->build_logger_limit_level(log::log_level::DEBUG);
    b->build_sink<log::stdout_sink>();
    b->build_sink<log::file_sink>("./logfile/file_sink.log");
    b->build_sink<log::rollsize_sink>("./logfile/roll-", 4096);
    auto logger = b->build();

    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    // size_t size = 0;
    // size_t cnt = 1;
    // while(size < 4096 * 10)
    // {
    //     logger->fatal(__FILE__, __LINE__, "测试日志-%d", cnt++);
    //     size += 80;
    // }

    size_t cnt = 0;
    while(cnt < 10000)
    {
        logger->fatal("%s-%d", "测试日志", cnt++);
    }
}

void test_buffer()
{
    // // 制造一个测试文件
    // std::unique_ptr<log::build_logger> b(new log::local_build_logger());
    // b->build_logger_name("sync_logger");
    // b->build_formatter("%d %l %f %m%N");
    // b->build_logger_type(log::logger_type::LOGGER_SYNC);
    // b->build_logger_limit_level(log::log_level::DEBUG);
    // b->build_sink<log::file_sink>("./logfile/file_sink.log");
    // auto logger = b->build();
    // size_t size = 0;
    // size_t cnt = 1;
    // while(size < 1024 * 1024 * 10)
    // {
    //     logger->fatal(__FILE__, __LINE__, "测试日志-%d", cnt++);
    //     size += 80;
    // }

    // 打开该文件并获取文件大小
    std::ifstream ifs("./logfile/file_sink.log", std::ios::binary);
    if(ifs.is_open() == false) {cout << "文件打开失败" << endl; return;}
    ifs.seekg(0, std::ios::end);//读写位置跳转到文件末尾
    size_t fsize = ifs.tellg();//获取当前位置到文件起始位置的偏移量
    ifs.seekg(0, std::ios::beg);//读写位置跳转到文件开头

    string str;
    str.resize(fsize);
    ifs.read(&str[0], fsize);
    if(ifs.good() == false) {cout << "文件读取失败" << endl; return;}
    ifs.close();

    cout << fsize << endl;
    log::buffer buffer;
    for(size_t i = 0; i < fsize; ++i)
    {
        buffer.push(&str[i], 1);
    }
    cout << buffer.readable_size() << endl;

    std::ofstream ofs("./logfile/buffer.log", std::ios::binary);
    if(ofs.is_open() == false) {cout << "文件打开失败2" << endl; return;}
    size_t rsize = buffer.readable_size();
    for(size_t i = 0; i < rsize; ++i)
    {
        ofs.write(buffer.begin(), 1);
        buffer.move_read(1);
    }
    ofs.close();

    // md5sum buffer.log
    // md5sum file_sink.log
}

// 测试异步日志器
void test_logger2()
{
    std::unique_ptr<log::build_logger> b(new log::local_build_logger());
    b->build_logger_name("async_logger");
    b->build_formatter("%n %d %l %f %m%N");
    b->build_logger_type(log::logger_type::LOGGER_ASYNC);
    b->build_logger_limit_level(log::log_level::DEBUG);
    b->build_sink<log::stdout_sink>();
    b->build_sink<log::file_sink>("./logfile/async.log");
    b->build_enable_async_unsafe();
    auto logger = b->build();

    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t cnt = 0;
    while(cnt < 100000)
    {
        logger->fatal(__FILE__, __LINE__, "测试日志-%d", cnt++);
    }
}

void _test_logger3()
{
    //log::logger::ptr l = log::logger_manage::get_instance().default_logger();
    log::logger::ptr l = log::logger_manage::get_instance().get_logger("violet");
    l->debug(__FILE__, __LINE__, "%s", "测试日志");
    l->info(__FILE__, __LINE__, "%s", "测试日志");
    l->warn(__FILE__, __LINE__, "%s", "测试日志");
    l->error(__FILE__, __LINE__, "%s", "测试日志");
    l->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t cnt = 0;
    while(cnt < 10000)
    {
        l->fatal(__FILE__, __LINE__, "测试日志-%d", cnt++);
    }
}

// 测试logger_manage和全局建造者global_logger_build
void test_logger3()
{
    std::unique_ptr<log::global_build_logger> b(new log::global_build_logger());
    b->build_logger_name("violet");
    b->build_sink<log::file_sink>("./logfile/temp.log");
    log::logger::ptr l = b->build();
    _test_logger3();
}

// 测试log.h头文件
void test_log_h()
{
    DEBUG("%s", "测试日志");
    INFO("%s", "测试日志");
    WARN("%s", "测试日志");
    ERROR("%s", "测试日志");
    FATAL("%s", "测试日志");
    // size_t cnt = 0;
    // while(cnt < 10000)
    // {
    //     FATAL("%s%d", "测试日志-", cnt++);
    // }
}

void _example()
{
    log::logger::ptr l = log::logger_manage::get_instance().get_logger("violet");
    l->debug("%s", "测试日志");
    l->info("%s", "测试日志");
    l->warn("%s", "测试日志");
    l->error("%s", "测试日志");
    l->fatal("%s", "测试日志");
    size_t cnt = 0;
    while(cnt < 10000)
    {
        l->fatal("%s-%d", "测试日志", cnt++);
    }
    DEBUG("%s", "测试日志结束");
    // ...
    FATAL("%s", "测试日志结束");
}

void example()
{
    std::unique_ptr<log::build_logger> b(new log::global_build_logger());
    b->build_logger_name("violet");
    b->build_formatter("[%d{%H:%M:%S}][%n][%t][%l][%f:%L]%T%m%N");
    b->build_logger_type(log::logger_type::LOGGER_ASYNC);
    b->build_logger_limit_level(log::log_level::DEBUG);
    b->build_sink<log::stdout_sink>();
    b->build_sink<log::file_sink>("./logfile/file_sink.log");
    b->build_sink<log::rollsize_sink>("./logfile/roll-", 1024 * 100);
    b->build();
    _example();
}

int main() 
{
    //test_util();
    //test_level();
    //test_format();
    //test_sink();
    //test_logger();
    //test_buffer();
    //test_logger2();
    //test_logger3();
    //test_log_h();
    example();
    return 0;
}